package cn.hairui.blog.controller;

import cn.hairui.blog.configure.WebLog;
import cn.hairui.blog.constant.PubConstant;
import cn.hairui.blog.entity.*;
import cn.hairui.blog.service.*;
import cn.hairui.blog.util.BlogUtil;
import cn.hairui.blog.util.DateUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author laoganbu
 * @since 2020-04-06
 */
@Controller

public class ArticalController {
    @Autowired
    private ArticalService articalService;

    @Autowired
    private TypeService typeService;

    @Autowired
    private TagService tagService;

    @Autowired
    private ArticaltagService articaltagService;

    @Autowired
    private MyinfoService myinfoService;

    @Autowired
    private UserService userService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private VisitrecordService visitrecordService;

    @Autowired
    private ViewrecordService viewrecordService;

    @Autowired
    private LikerecordService likerecordService;

    // 查看文章
    @GetMapping("/blog/{id}")
    @WebLog(description = "查看文章")
    public String blog(@PathVariable int id, HttpServletRequest request, Model model) {
        // 获取文章
        Artical artical = articalService.getById(id);
        String result = "";// 默认返回页面
        if (artical != null) {
            String showFlag = artical.getShowFlag();
            if (PubConstant.YES_NO_Y.equals(showFlag)) {
                model.addAttribute("artical", artical);
                result = "blog";
            } else {
                // 权限控制
                User user = (User) request.getSession().getAttribute(PubConstant.GLOBAL_SESSION_NAME);
                if (user == null) {
                    result = "error/403";
                } else {
                    if (PubConstant.USER_TYPE_SUPER_ADMIN.equals(user.getType())) {
                        // 超级管理员可以看见所有
                        model.addAttribute("artical", artical);
                        result = "blog";
                    } else {
                        // 非管理员
                        String createId = artical.getCreateId();
                        if (user.getAccount().equals(createId)) {
                            // 本人创建
                            model.addAttribute("artical", artical);
                            result = "blog";
                        } else {
                            // 非本人创建
                            result = "error/403";
                        }
                    }
                }
            }
        } else {
            return "error/404";
        }

        if ("blog".equals(result)) {
            // 分类信息
            List<Map> typesList = typeService.selectByShowFlag(PubConstant.YES_NO_Y, PubConstant.INDEX_TOP_TYPE_COUNT);
            model.addAttribute("types", typesList);

            // 标签信息
            List<Map> tagList = tagService.selectTags(PubConstant.INDEX_TOP_TAG_COUNT, PubConstant.YES_NO_Y);
            model.addAttribute("tags", tagList);

            // 最新推荐
            List<Artical> newList = articalService.listTop(PubConstant.INDEX_TOP_NEWARTICAL_COUNT, "create_time");
            model.addAttribute("newarticals", newList);

            // 本站信息
            int artical_count = articalService.count();// 文章总数
            int type_count = typeService.count();// 分类总数
            int tag_count = tagService.count();// 标签总数
            int comment_count = messageService.count();
            int visit_count = visitrecordService.count();
            int today_visit_count = visitrecordService.countByDate(DateUtil.getCurrentDate());

            Map webinfo = new HashMap();
            webinfo.put("artical_count", artical_count);
            webinfo.put("type_count", type_count);
            webinfo.put("tag_count", tag_count);
            webinfo.put("comment_count", comment_count);
            webinfo.put("visit_count", visit_count);
            webinfo.put("today_visit_count", today_visit_count);

            model.addAttribute("webinfo", webinfo);
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("account", artical.getCreateId());
            User user = userService.getOne(queryWrapper);
            model.addAttribute("user", user);

            Type type = typeService.getById(artical.getTypeId());
            model.addAttribute("type", type);

            //这里只是查询了上一篇下一篇文章，并没有根据当前分类或者标签进行判断
            Artical articalLast = articalService.findLastArtical(id);
            Artical articalNext = articalService.findNextArtical(id);

            model.addAttribute("artical_last", articalLast);
            model.addAttribute("artical_next", articalNext);
            //判断ipAddress是否本机访问
            String ipAddress = request.getRemoteAddr();
            if (ipAddress != null) {
                if (PubConstant.LOCAL_IP_ADDRESS_STR.equals(ipAddress)) {
                    ipAddress = PubConstant.LOCAL_IP_ADDRESS_STR_FORMAT;
                }
                //判断今日是否有访问过
                QueryWrapper<Viewrecord> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("VISIT_DATE", DateUtil.getCurrentDate());
                queryWrapper1.eq("IP_ADDRESS", ipAddress);
                queryWrapper1.eq("ARTICAL_ID", id);

                Viewrecord viewrecord = viewrecordService.getOne(queryWrapper1);
                if (viewrecord == null) {
                    //无记录
                    Viewrecord domain = new Viewrecord();
                    domain.setIpAddress(ipAddress);
                    domain.setVisitDate(DateUtil.getCurrentDate());
                    domain.setArticalId(id);
                    domain.setLastVisitTime(DateUtil.getCurrentTime());
                    domain.setVisitCount(1);
                    viewrecordService.save(domain);
                } else {
                    //有记录
                    String lastTime = viewrecord.getLastVisitTime();
                    String nowTime = DateUtil.getCurrentTime();
                    int betweenMin = DateUtil.judgeMinutesTimeBetween(lastTime, nowTime);

                    if ((betweenMin / 60) > PubConstant.VISITED_NEW_HOURS) {
                        //超出规定时间 认定为新的一次访问
                        viewrecord.setLastVisitTime(DateUtil.getCurrentTime());
                        viewrecord.setVisitCount(viewrecord.getVisitCount() + 1);
                    } else {
                        //在规定时间内 认定为同一次访问
                        viewrecord.setLastVisitTime(DateUtil.getCurrentTime());
                    }
                    viewrecordService.saveOrUpdate(viewrecord);
                }
            }

            //获取访问次数
            int view_times = viewrecordService.countViewRecord(id);
            model.addAttribute("view_times", view_times);

            //判断ipAddress是否存在点赞记录
            Likerecord likerecord = likerecordService.selectByIpAndArticalId(ipAddress, id);
            if (likerecord == null) {
                model.addAttribute("like_flag", PubConstant.YES_NO_N);
            } else {
                model.addAttribute("like_flag", PubConstant.YES_NO_Y);
            }
            //获取点赞次数
            int like_times = likerecordService.countLikeRecord(id);
            model.addAttribute("like_times", like_times);
            //将文章信息更新
            artical.setLikeTimes(like_times);
            artical.setViewTimes(view_times);
            articalService.updateLVTimesById(id, like_times, view_times);
        }
        Myinfo myinfo = myinfoService.getById(PubConstant.MY_INFO_ID);
        model.addAttribute("myinfo", myinfo);
        return result;
    }

    @RequestMapping(value = "/archives")
    public String archives(Model model) {
        // 我的信息
        Myinfo myinfo = myinfoService.getById(PubConstant.MY_INFO_ID);
        model.addAttribute("myinfo", myinfo);
        // 分类信息
        List<Map> typesList = typeService.selectByShowFlag(PubConstant.YES_NO_Y, PubConstant.INDEX_TOP_TYPE_COUNT);
        model.addAttribute("types", typesList);

        // 标签信息
        List<Map> tagList = tagService.selectTags(PubConstant.INDEX_TOP_TAG_COUNT, PubConstant.YES_NO_Y);
        model.addAttribute("tags", tagList);

        // 最新推荐
        List<Artical> newList = articalService.listTop(PubConstant.INDEX_TOP_NEWARTICAL_COUNT, "create_time");
        model.addAttribute("newarticals", newList);

        // 本站信息
        int artical_count = articalService.count();// 文章总数
        int type_count = typeService.count();// 分类总数
        int tag_count = tagService.count();// 标签总数
        int comment_count = messageService.count();
        int visit_count = visitrecordService.count();
        int today_visit_count = visitrecordService.countByDate(DateUtil.getCurrentDate());

        Map webinfo = new HashMap();
        webinfo.put("artical_count", artical_count);
        webinfo.put("type_count", type_count);
        webinfo.put("tag_count", tag_count);
        webinfo.put("comment_count", comment_count);
        webinfo.put("visit_count", visit_count);
        webinfo.put("today_visit_count", today_visit_count);
        model.addAttribute("webinfo", webinfo);

        // 获取所有年代和文章数量
        List<Map> articalyearList = articalService.selectYearAndCount(PubConstant.YES_NO_Y);

        List<Map> result = new ArrayList();
        Iterator iterator = articalyearList.iterator();
        while (iterator.hasNext()) {
            Map map = (Map) iterator.next();
            String year = String.valueOf(map.get("year"));
            String count = String.valueOf(map.get("count"));
            Map yearartical = new HashMap();
            yearartical.put("year", year);
            yearartical.put("count", count);

            List<Artical> articals = articalService.selectByYearAndShowFlag(year, PubConstant.YES_NO_Y,
                    PubConstant.ARCHIVES_SHOW_COUNT);
            yearartical.put("articals", articals);
            result.add(yearartical);
        }
        model.addAttribute("result", result);

        return "archives";
    }

    @RequestMapping(value = "/archive/{year}", method = RequestMethod.GET)
    public String archive(@PathVariable int year, HttpServletRequest request, Model model) {
        // 我的信息
        Myinfo myinfo = myinfoService.getById(PubConstant.MY_INFO_ID);
        model.addAttribute("myinfo", myinfo);

        // 分类信息
        List<Map> typesList = typeService.selectByShowFlag(PubConstant.YES_NO_Y, PubConstant.INDEX_TOP_TYPE_COUNT);
        model.addAttribute("types", typesList);

        // 标签信息
        List<Map> tagList = tagService.selectTags(PubConstant.INDEX_TOP_TAG_COUNT, PubConstant.YES_NO_Y);
        model.addAttribute("tags", tagList);

        // 最新推荐
        List<Artical> newList = articalService.listTop(PubConstant.INDEX_TOP_NEWARTICAL_COUNT, "create_time");
        model.addAttribute("newarticals", newList);

        // 本站信息
        int artical_count = articalService.count();// 文章总数
        int type_count = typeService.count();// 分类总数
        int tag_count = tagService.count();// 标签总数
        int comment_count = messageService.count();
        int visit_count = visitrecordService.count();
        int today_visit_count = visitrecordService.countByDate(DateUtil.getCurrentDate());

        Map webinfo = new HashMap();
        webinfo.put("artical_count", artical_count);
        webinfo.put("type_count", type_count);
        webinfo.put("tag_count", tag_count);
        webinfo.put("comment_count", comment_count);
        webinfo.put("visit_count", visit_count);
        webinfo.put("today_visit_count", today_visit_count);

        model.addAttribute("webinfo", webinfo);

        // 分页信息 文章信息
        Integer pageNum = null;
        String pageNumStr = request.getParameter("pageIndex");
        if (pageNumStr != null) {
            pageNum = Integer.parseInt(pageNumStr);
        }
        if (pageNum == null) {
            pageNum = 1;
        }
        int pageSize = PubConstant.INDEX_PAGE_SIZE;
        PageHelper.startPage(pageNum, pageSize);
        List<Map> articalList = articalService.selectByShowFlagAndYear(PubConstant.YES_NO_Y, year);// 默认只展示站长开放的内容
        PageInfo<Map> pageInfo = new PageInfo<Map>(articalList);
        model.addAttribute("articals", articalList);

        model.addAttribute("pageInfo", pageInfo);
        model.addAttribute("pageIndex", pageNum);
        model.addAttribute("pageSize", pageSize);

        model.addAttribute("year", year);
        return "archive";
    }

    @RequestMapping(value = "/thumbup")
    @ResponseBody
    public String thumbup(HttpServletRequest request, int id) {
        String ipAddress = request.getRemoteAddr();
        if (ipAddress != null) {
            if (PubConstant.LOCAL_IP_ADDRESS_STR.equals(ipAddress)) {
                ipAddress = "127.0.0.1";
            }
            //通过文章编号和id地址查询是否存在点赞记录
            Likerecord likerecord = likerecordService.selectByIpAndArticalId(ipAddress, id);
            if (likerecord == null) {
                likerecord = new Likerecord();
                likerecord.setArticalId(id);
                likerecord.setIpAddress(ipAddress);
                likerecord.setLikeDate(DateUtil.getCurrentDate());
                likerecord.setLastLikeTime(DateUtil.getCurrentTime());
                likerecordService.saveOrUpdate(likerecord);

                //获取点赞次数
                int like_times = likerecordService.countLikeRecord(id);
                Artical artical = new Artical();
                artical.setId(id);
                artical.setLikeTimes(like_times);
                articalService.updateById(artical);
            }
        }
        Map map = new HashMap<Object, Object>();

        map.put(PubConstant.flag, PubConstant.success);
        return JSONUtils.toJSONString(map);
    }

    //// ==========================后台==============================///////
    // 列表页面
    @RequestMapping(value = "/manage/artical/list", method = RequestMethod.GET)
    public String list() {
        return "page/artical/list";
    }

    // 新增页面
    @RequestMapping(value = "/manage/artical/add", method = RequestMethod.GET)
    public String add(Model model) {
        // 加载分类字典
        List<Map> typeList = typeService.listByManageShow();
        model.addAttribute("typeDic", typeList);

        // 加载标签字典
        List<Map> tagList = tagService.list();
        model.addAttribute("tagDic", tagList);

        return "page/artical/add";
    }

    // 修改页面
    @RequestMapping(value = "/manage/artical/update")
    public String categoryUpdate(HttpServletRequest request, Model model) {
        int id = Integer.parseInt(request.getParameter("id"));
        Artical artical = articalService.getById(id);
        model.addAttribute("artical", artical);

        QueryWrapper<Articaltag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("artical_id", id);
        List<Articaltag> articaltagList = articaltagService.list(queryWrapper);
        model.addAttribute("tag", articaltagList);

        // 加载分类字典
        List<Map> typeList = typeService.listByManageShow();
        model.addAttribute("typeDic", typeList);

        // 加载标签字典
        List<Map> tagList = tagService.list();

        // 重新构造标签字典 标注已选
        List<Map> tagListNew = new ArrayList<>();
        for (int i = 0; i < tagList.size(); i++) {
            String tagid = String.valueOf(tagList.get(i).get("id"));
            Map m = new HashMap();
            m.put("id", tagid);
            m.put("name", tagList.get(i).get("name"));

            String flag = PubConstant.YES_NO_N;
            for (int j = 0; j < articaltagList.size(); j++) {
                String articaltagid = String.valueOf(articaltagList.get(j).getTagId());
                if (tagid.equals(articaltagid)) {
                    flag = PubConstant.YES_NO_Y;
                    break;
                }
            }
            m.put(PubConstant.flag, flag);
            tagListNew.add(m);
        }
        model.addAttribute("tagDic", tagListNew);
        return "page/artical/update";
    }

    // 列表数据
    @RequestMapping(value = "/manage/artical/data")
    @ResponseBody
    public String data(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute(PubConstant.GLOBAL_SESSION_NAME);
        if (user != null && PubConstant.USER_TYPE_SUPER_ADMIN.equals(user.getType())) {
            Map map = new HashMap<Object, Object>();
            int pageSize = 10;// 默认每页显示5条记录
            int pageNum = 1;
            try {
                pageNum = Integer.parseInt(request.getParameter("page"));
                pageSize = Integer.parseInt(request.getParameter("limit"));
            } catch (Exception e) {
            }
            PageHelper.startPage(pageNum, pageSize);
            List<Map> typeList = articalService.selectByAccount(user.getAccount());

            PageInfo<Map> pageInfo = new PageInfo<Map>(typeList);
            map.put("data", typeList);
            map.put("code", 0);
            map.put("count", pageInfo.getTotal());
            return JSONUtils.toJSONString(map);
        } else {
            return null;
        }
    }

    // 新增数据
    @RequestMapping(value = "/manage/artical/addData")
    @ResponseBody
    @Transactional
    public String add(HttpServletRequest request, Artical artical, int[] tag) {
        Map map = new HashMap<Object, Object>();

        // 添加创建时间
        artical.setCreateDate(DateUtil.getCurrentDate());
        artical.setCreateTime(DateUtil.getCurrentTime());

        // TODO 背景图片从系统中1-35.jpg选择一张 后期可以优化改造
        int i = new Random().nextInt(34) + 1;// 1-35随机图片
        String imgPath = i + ".jpg";
        artical.setIndexPicture(imgPath);

        // 初始化点赞次数
        artical.setLikeTimes(0);
        artical.setViewTimes(0);
        // 原创文章将转载信息置空
        if (PubConstant.REPRINT_TYPE_0.equals(artical.getReprintFlag())) {
            artical.setReprintUrl(null);
        }
        int id = articalService.add(artical);

        // 插入articaltag表
        if (tag != null && tag.length > 0) {
            for (int t : tag) {
                Articaltag articaltag = new Articaltag();
                articaltag.setArticalId(id);
                articaltag.setTagId(t);
                articaltagService.save(articaltag);
            }
        }
        map.put(PubConstant.flag, PubConstant.success);
        return JSONUtils.toJSONString(map);
    }

    // 更新数据
    @RequestMapping(value = "/manage/artical/updateData")
    @ResponseBody
    @Transactional
    public String updateData(HttpServletRequest request, Artical artical, int[] tag) {
        Map map = new HashMap<Object, Object>();

        // 添加更新时间
        artical.setUpdateTime(DateUtil.getCurrentTime());

        // 原创文章将转载信息置空
        if (PubConstant.REPRINT_TYPE_0.equals(artical.getReprintFlag())) {
            artical.setReprintUrl(null);
        }
        articalService.saveOrUpdate(artical);

        // 删除articaltag表
        int articalId = artical.getId();
        Map param = new HashMap();
        param.put("artical_id", articalId);
        articaltagService.removeByMap(param);
        // 插入articaltag表
        if (tag != null && tag.length > 0) {
            for (int t : tag) {
                Articaltag articaltag = new Articaltag();
                articaltag.setArticalId(articalId);
                articaltag.setTagId(t);
                articaltagService.save(articaltag);
            }
        }
        map.put(PubConstant.flag, PubConstant.success);
        return JSONUtils.toJSONString(map);
    }

    // 内容编辑页面
    @RequestMapping(value = "/manage/artical/edit")
    public String edit(HttpServletRequest request, int id, Model model) {

        Myinfo myinfo = myinfoService.getById(PubConstant.MY_INFO_ID);
        model.addAttribute("myinfo", myinfo);

        Artical artical = articalService.getById(id);
        model.addAttribute("artical", artical);

        return "page/artical/markdown";
    }

    // 修改内容
    @RequestMapping(value = "/manage/artical/updateContent")
    @ResponseBody
    @Transactional
    public String updateContent(HttpServletRequest request, Artical artical) {
        Map map = new HashMap<Object, Object>();
        artical.setUpdateTime(DateUtil.getCurrentTime());
        articalService.saveOrUpdate(artical);
        map.put(PubConstant.flag, PubConstant.success);
        return JSONUtils.toJSONString(map);
    }

    // 修改展示标志
    @RequestMapping(value = "/manage/artical/show")
    @ResponseBody
    @Transactional
    public String show(HttpServletRequest request) {
        Map map = new HashMap<Object, Object>();
        int id = Integer.parseInt(request.getParameter("id"));
        Artical artical = articalService.getById(id);
        String flag = "";
        if (PubConstant.YES_NO_Y.equals(artical.getShowFlag())) {
            // 取消展示
            flag = PubConstant.YES_NO_N;
        } else {
            // 展示
            flag = PubConstant.YES_NO_Y;
        }
        artical.setShowFlag(flag);
        articalService.saveOrUpdate(artical);
        map.put(PubConstant.flag, flag);
        return JSONUtils.toJSONString(map);
    }

    // 删除数据
    @RequestMapping(value = "/manage/artical/delete", method = RequestMethod.POST)
    @ResponseBody
    @Transactional
    public String delete(@Param(value = "id") int id, HttpServletRequest request) {
        Map map = new HashMap();
        articalService.removeById(id);

        // 删除文章关联标签
        Map param = new HashMap();
        param.put("artical_id", id);
        articaltagService.removeByMap(param);

        map.put(PubConstant.flag, PubConstant.success);
        return JSONUtils.toJSONString(map);
    }

    // 批量删除
    @RequestMapping(value = "/manage/artical/deleteBatch", method = RequestMethod.POST)
    @ResponseBody
    @Transactional
    public String deleteBatch(@Param(value = "ids") Integer[] ids) {
        Map map = new HashMap();
        List<Integer> idsList = Arrays.asList(ids);
        articalService.removeByIds(idsList);
        map.put(PubConstant.flag, PubConstant.success);
        return JSONUtils.toJSONString(map);
    }

    @Value("${upload_path}")
    private String uploadPath;

    @Value("${virtual_upload_path}")
    private String virtualUploadPath;

    @RequestMapping("/manage/artical/uploadImage")
    public @ResponseBody
    Map<String, Object> demo(
            @RequestParam(value = "editormd-image-file", required = false) MultipartFile file,
            HttpServletRequest request) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        String contextName = request.getContextPath();
        String fileName = file.getOriginalFilename();

        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        // 重新生成文件名
        fileName = BlogUtil.getUUIDUpperCase() + suffixName;
        File targetPath = new File(uploadPath + PubConstant.ARTICAL_DIR);
        if (!targetPath.exists()) {
            targetPath.mkdirs();
        }
        // 保存
        try {
            byte[] bytes = file.getBytes();
            Path path = Paths.get(uploadPath + PubConstant.ARTICAL_DIR + fileName);
            Files.write(path, bytes);
            resultMap.put("success", 1);
            resultMap.put("message", "上传成功！");
            resultMap.put("url", contextName + virtualUploadPath + PubConstant.ARTICAL_DIR + fileName);
        } catch (Exception e) {
            resultMap.put("success", 0);
            resultMap.put("message", "上传失败！");
            e.printStackTrace();
        }
        return resultMap;
    }

}
